package com.jingdianjichi.project.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.jingdianjichi.project.common.enums.IsDeletedFlagEnum;
import com.jingdianjichi.project.domain.bo.SubjectCategoryBo;
import com.jingdianjichi.project.domain.bo.SubjectLabelBo;
import com.jingdianjichi.project.domain.convert.SubjectCategoryConverter;
import com.jingdianjichi.project.domain.service.SubjectCategoryDomainService;
import com.jingdianjichi.project.domain.util.CacheUtil;
import com.jingdianjichi.project.infra.basic.entity.SubjectCategory;
import com.jingdianjichi.project.infra.basic.entity.SubjectLabel;
import com.jingdianjichi.project.infra.basic.entity.SubjectMapping;
import com.jingdianjichi.project.infra.basic.service.SubjectCategoryService;
import com.jingdianjichi.project.infra.basic.service.SubjectLabelService;
import com.jingdianjichi.project.infra.basic.service.SubjectMappingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * ClassName:SubjectCategoryDomainServiceImpl
 * Package:com.jingdianjichi.subject.domain.service.impl
 * Description:
 *
 * @Author fst
 * @Create 2024/9/26 15:39
 * @Version 1.0
 */
@Slf4j
@Service
public class SubjectCategoryDomainServiceImpl implements SubjectCategoryDomainService
{
    @Resource
    private SubjectCategoryService subjectCategoryService;

    @Resource
    private SubjectMappingService subjectMappingService;

    @Resource
    private SubjectLabelService subjectLabelService;

    @Resource
    private ThreadPoolExecutor labelThreadPool;

    @Resource
    private CacheUtil cacheUtil;




    @Override
    public void add(SubjectCategoryBo subjectCategoryBo) {
        //对象转化

        if(log.isInfoEnabled())
        {
            log.info("SubjectCategoryController.add.Bo:{}", JSON.toJSONString(subjectCategoryBo));
        }

        SubjectCategory subjectCategory = SubjectCategoryConverter.
                INSTANCE.
                convertBoToCategory(subjectCategoryBo);

        subjectCategoryService.insert(subjectCategory);
    }
    public  void update(SubjectCategoryBo subjectCategoryBo)
    {
        if(log.isInfoEnabled())
        {
            log.info("SubjectCategoryController.update.Bo:{}", JSON.toJSONString(subjectCategoryBo));
        }

        SubjectCategory subjectCategory = SubjectCategoryConverter.
                INSTANCE.
                convertBoToCategory(subjectCategoryBo);

        subjectCategoryService.update(subjectCategory);
    }

    public List<SubjectCategoryBo> queryPrimaryCategory(SubjectCategoryBo subjectCategoryBo)
    {
        if(log.isInfoEnabled())
        {
            log.info("SubjectCategoryController.queryPrimaryCategoty.Bo:{}", JSON.toJSONString(subjectCategoryBo));
        }

        SubjectCategory subjectCategory = SubjectCategoryConverter.
                INSTANCE.
                convertBoToCategory(subjectCategoryBo);
        List<SubjectCategory> subjectCategoryList=subjectCategoryService.queryCategory(subjectCategory);

        List<SubjectCategoryBo> subjectCategoryBoList = SubjectCategoryConverter.INSTANCE.convertBoToCategoryList(subjectCategoryList);


        subjectCategoryBoList.forEach(bo->
        {
            Integer count=subjectCategoryService.querySubjectCount(bo.getId());
            bo.setCount(count);
        });


        return subjectCategoryBoList;
    }

    public List<SubjectCategoryBo> queryCategory(SubjectCategoryBo subjectCategoryBo)
    {
        if(log.isInfoEnabled())
        {
            log.info("SubjectCategoryController.queryCategory.Bo:{}", JSON.toJSONString(subjectCategoryBo));
        }

        SubjectCategory subjectCategory = SubjectCategoryConverter.
                INSTANCE.
                convertBoToCategory(subjectCategoryBo);

        List<SubjectCategory> subjectCategoryList=subjectCategoryService.queryCategory(subjectCategory);

        List<SubjectCategoryBo> subjectCategoryBoList = SubjectCategoryConverter.INSTANCE.convertBoToCategoryList(subjectCategoryList);

        return subjectCategoryBoList;
    }

    public  void delete(SubjectCategoryBo subjectCategoryBo)
    {
        if(log.isInfoEnabled())
        {
            log.info("SubjectCategoryController.delete.Bo:{}", JSON.toJSONString(subjectCategoryBo));
        }

        SubjectCategory subjectCategory = SubjectCategoryConverter.
                INSTANCE.
                convertBoToCategory(subjectCategoryBo);

        subjectCategoryService.delete(subjectCategory);
    }

    public List<SubjectCategoryBo> queryCategoryAndLabel(SubjectCategoryBo subjectCategoryBo)
    {
        Long id=subjectCategoryBo.getId();

        String cacheKey="queryCategoryAndLabel."+id;

        List<SubjectCategoryBo>  subjectCategoryBoList = cacheUtil.getResult(cacheKey, SubjectCategoryBo.class, (key) -> getSubjectCategoryBos(id));

        return subjectCategoryBoList;
    }


    private List<SubjectCategoryBo> getSubjectCategoryBos(Long categoryId) {
        //查询大类下所有的分类
        SubjectCategory subjectCategory = new SubjectCategory();

        subjectCategory.setParentId(categoryId);

        subjectCategory.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());

        List<SubjectCategory> subjectCategoryList = subjectCategoryService.queryCategory(subjectCategory);


        //查询标签
        List<SubjectCategoryBo> subjectCategoryBoList = SubjectCategoryConverter.INSTANCE.convertBoToCategoryList(subjectCategoryList);


        //通过线程池优化
        List<CompletableFuture<Map<Long, List<SubjectLabelBo>>>> completableFutureList =
                subjectCategoryBoList.stream().map(category ->
                CompletableFuture.supplyAsync(() -> getlabelBOList(category),
                        labelThreadPool)).collect(Collectors.toList());

        Map<Long,List<SubjectLabelBo>> map =new HashMap<>();

        completableFutureList.forEach(future->
        {
            try {
                Map<Long, List<SubjectLabelBo>> ResultMap = future.get();
                map.putAll(ResultMap);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        subjectCategoryBoList.forEach(category->
        {
            category.setLabelList(map.get(category.getId()));
        });

        return subjectCategoryBoList;
    }


    private Map<Long,List<SubjectLabelBo>>  getlabelBOList(SubjectCategoryBo category)
    {
        if(log.isInfoEnabled())
        {
            log.info("getlabelBOList:{}", JSON.toJSONString(category));
        }
        SubjectMapping subjectMapping=new SubjectMapping();
        subjectMapping.setCategoryId(category.getId());

        List<SubjectMapping> subjectMappingList=subjectMappingService.queryLabelId(subjectMapping);

        if(CollectionUtils.isEmpty(subjectMappingList)) return null;

        List<Long> labelIdList = subjectMappingList.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());


        List<SubjectLabel> labelList=new ArrayList<>();

        labelList = subjectLabelService.batchQueryById(labelIdList);

        List<SubjectLabelBo> labelBoList =new ArrayList<>();

        labelList.forEach(label->{
            SubjectLabelBo subjectLabelBo=new SubjectLabelBo();

            subjectLabelBo.setCategoryId(label.getCategoryId());

            subjectLabelBo.setLabelName(label.getLabelName());

            subjectLabelBo.setSortNum(label.getSortNum());

            subjectLabelBo.setId(label.getId());

            labelBoList.add(subjectLabelBo);
        });

        Map<Long,List<SubjectLabelBo>> map=new HashMap<>();

        map.put(category.getId(),labelBoList);

        return map;
    }
}
